package com.bestcem.xm.om.grpc.client;

import com.bestcem.bp.grpc.v1.base.Page;
import com.bestcem.bp.pay.grpc.v1.common.PeriodTime;
import com.bestcem.bp.pay.grpc.v1.services.*;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.common.core.sign.grpc.core.GrpcTemplate;
import com.bestcem.xm.common.core.uitls.GrpcDateUtil;
import com.bestcem.xm.om.controller.param.ListOrderParam;
import com.bestcem.xm.om.grpc.service.converter.OmOrderConverter;
import com.bestcem.xm.om.grpc.service.dto.OrderDTO;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
import zhongyan.xm.base.v1.Base;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * PaymentService
 *
 * @author zq.ding <zq.ding@idiaoyan.com>
 * @version v1.0
 * @date 2021/7/27 10:40
 */
@Slf4j
@Service(value = "omPayGrpcService")
public class PaymentService {

    @GrpcClient(GrpcClientNames.PAY)
    private PaymentServiceGrpc.PaymentServiceBlockingStub stub;

    @Resource
    private GrpcTemplate grpcTemplate;

    private static final String GET_ORDER_ERROR_MSG = "[OM] pay getOrder {} Error; ErrorMsg: {}";

    public Order getOrder(String orderNo) {
        GetOrderRequest.Builder builder = GetOrderRequest.newBuilder();
        builder.setOrderNo(orderNo);
        try {
            GetOrderRequest request = builder.build();
            // 加签并请求
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            GetOrderResponse response = stub.getOrder(request);
            if (Objects.isNull(response) || Base.Code.ERROR_VALUE == response.getStatus().getCodeValue()) {
                log.error(GET_ORDER_ERROR_MSG, orderNo, response);
                return null;
            }
            return response.getOrder();
        } catch (Exception e) {
            log.error(GET_ORDER_ERROR_MSG, orderNo, e.getMessage(), e);
            return null;
        }
    }

    public OrderDTO getOrderStatus(String orderNo) {
        GetOrderStatusRequest.Builder builder = GetOrderStatusRequest.newBuilder();
        builder.setOrderNo(orderNo);
        try {
            GetOrderStatusRequest request = builder.build();
            // 加签并请求
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            GetOrderStatusResponse response = stub.getOrderStatus(request);
            if (Objects.isNull(response) || Base.Code.ERROR_VALUE == response.getStatus().getCodeValue()) {
                log.error(GET_ORDER_ERROR_MSG, orderNo, response);
                return null;
            }
            return OmOrderConverter.convertToOrderDTO(response.getOrder());
        } catch (Exception e) {
            log.error(GET_ORDER_ERROR_MSG, orderNo, e.getMessage(), e);
            return null;
        }
    }

    public String completeOrder(Order order) {
        if (Objects.isNull(order)) {
            return null;
        }
        CompleteOrderRequest.Builder builder = CompleteOrderRequest.newBuilder();
        builder.setOrder(order);
        try {
            CompleteOrderRequest request = builder.build();
            // 加签并请求
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            CompleteOrderResponse response = stub.completeOrder(request);
            if (Objects.isNull(response) || Base.Code.ERROR_VALUE == response.getStatus().getCodeValue()) {
                log.error(GET_ORDER_ERROR_MSG, order, response);
                return null;
            }
            return response.getOrderNo();
        } catch (Exception e) {
            log.error(GET_ORDER_ERROR_MSG, order, e.getMessage(), e);
            return null;
        }
    }

    /**
     * // 取消订单请求
     * // 处于已创建状态的订单允许取消
     *
     * @param orderNo
     * @return
     */
    public CancelOrderResponse cancelOrder(String orderNo) {
        CancelOrderRequest.Builder builder = CancelOrderRequest.newBuilder();
        builder.setOrderNo(orderNo);
        try {
            CancelOrderRequest request = builder.build();
            // 加签并请求
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            CancelOrderResponse response = stub.cancelOrder(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR_VALUE == response.getStatus().getCodeValue()) {
                log.error(GET_ORDER_ERROR_MSG, orderNo, response);
                return null;
            }
            return response;
        } catch (Exception e) {
            log.error(GET_ORDER_ERROR_MSG, orderNo, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据参数查询订单列表
     *
     * @param param
     * @return
     */
    public ListOrdersResponse listOrders(ListOrderParam param) {
        ListOrdersRequest.Builder builder = ListOrdersRequest.newBuilder();
        if (log.isInfoEnabled()) {
            log.info("[om] listOrders param:{}", param.toString());
        }
        if (param.getPaging() != null) {
            builder.setPaging(param.getPaging());
        }
        if (Boolean.TRUE.equals(param.getPaging())) {
            builder.setPage(Page.newBuilder().setPage(param.getPage()).setSize(param.getRowsPerPage()).build());
        }
        if (param.getStatus() != null) {
            builder.setStatusValue(param.getStatus());
        }
        if (param.getPayConfirmed() != null) {
            builder.setPayConfirmed(param.getPayConfirmed());
        }
        if (param.getPayMethod() != null) {
            builder.setPayMethodValue(param.getPayMethod());
        }
        if (param.getSubmitPeriod() != null &&
                param.getSubmitPeriod().getStartTime() != null && param.getSubmitPeriod().getEndTime() != null) {
            PeriodTime time = PeriodTime.newBuilder()
                    .setStartTime(GrpcDateUtil.getTimestamp(param.getSubmitPeriod().getStartTime()))
                    .setEndTime(GrpcDateUtil.getTimestamp(param.getSubmitPeriod().getEndTime()))
                    .build();
            builder.setSubmitPeriod(time);
        }
        if (param.getPayPeriod() != null && param.getPayPeriod().getStartTime() != null && param.getPayPeriod().getEndTime() != null) {
            PeriodTime time = PeriodTime.newBuilder()
                    .setStartTime(GrpcDateUtil.getTimestamp(param.getPayPeriod().getStartTime()))
                    .setEndTime(GrpcDateUtil.getTimestamp(param.getPayPeriod().getEndTime()))
                    .build();
            builder.setPayPeriod(time);
        }
        if (StringUtils.isNotBlank(param.getDescription())) {
            builder.setDescription(param.getDescription());
        }
        if (StringUtils.isNotBlank(param.getOrderNo())) {
            builder.setOrderNo(param.getOrderNo());
        }
        if (StringUtils.isNotBlank(param.getPayerOrgName())) {
            builder.setPayerOrgName(param.getPayerOrgName());
        }
        if (StringUtils.isNotBlank(param.getPayerOrgCode())) {
            builder.setPayerOrgCode(param.getPayerOrgCode());
        }
        if (StringUtils.isNotBlank(param.getPayerAccountNo())) {
            builder.setPayerAccountNo(param.getPayerAccountNo());
        }
        if (StringUtils.isNotBlank(param.getOutOrderNo())) {
            builder.setOutOrderNo(param.getOutOrderNo());
        }
        if (StringUtils.isNotBlank(param.getPayerUserName())) {
            builder.setPayerUserName(param.getPayerUserName());
        }
        if (log.isInfoEnabled()) {
            log.info("[OM] listOrders builder:{}", builder.toString());
        }
        try {
            ListOrdersRequest request = builder.build();
            // 加签并请求
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            ListOrdersResponse response = stub.listOrders(request);
            if (Objects.isNull(response) || Base.Code.ERROR_VALUE == response.getStatus().getCodeValue()) {
                log.error(GET_ORDER_ERROR_MSG, param, response);
                return null;
            }
            return response;
        } catch (Exception e) {
            log.error(GET_ORDER_ERROR_MSG, param, e.getMessage(), e);
            return null;
        }
    }
}
